package org.wx.io.nio;


import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;


/**
 * NIO 的网络socket
 *
 * @author wangxun
 * @version 1.0
 * @description: serverSocket
 * @date 2021/2/1 4:31 下午
 */
@Slf4j
public class NIOServerSocket {

    public static void main(String[] args) throws IOException {

        ServerSocketChannel channel = ServerSocketChannel.open();
        /**
         * 设置为非阻塞
         */
        channel.configureBlocking(false);
        channel.bind(new InetSocketAddress(9999));
        log.info("服务器开启");
        /**
         * 开启选择器
         */
        Selector selector = Selector.open();
        /**
         * 将channel注册到selector上
         */
        channel.register(selector, SelectionKey.OP_ACCEPT);

        /**
         * 返回已经发生状态变更
         */

        while (true) {

            log.info("selector size {}",selector.keys().size());


            while (selector.select() > 0) {
                Set<SelectionKey> selectionKeys = selector.selectedKeys();

                Iterator<SelectionKey> iterator = selectionKeys.iterator();

                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    iterator.remove();
                    if (key.isAcceptable()) {
                        log.info("此时的channel:{}", key.channel().toString());
                        /**
                         * 与客户端通讯的socket
                         */
                        ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                        SocketChannel client = ssc.accept();
                        // 非阻塞
                        client.configureBlocking(false);
                        /**
                         * 注册进selector 监听可读状态
                         */
                        client.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(4096));
                    } else if (key.isReadable()) {
                   /**
                     * 与客户端通讯的socket
                     */
                    SocketChannel client = (SocketChannel)key.channel();
                    ByteBuffer byteBuffer = (ByteBuffer)key.attachment();
                    client.read(byteBuffer);
                    log.info("客户端channel:{} 发送的信息:{}",client.getRemoteAddress(),new String(byteBuffer.array()));
                    }
                }
            }
        }
    }
}
